#include "callother.h"

#define N_INTOBJECTS	1000

static CoInt *free_list = NULL;

static CoInt *fill_free_list(void)
{
	CoInt *p, *q;

	p = CO_NEW(CoInt, N_INTOBJECTS);
	if (p == NULL) {
            /* TODO: [ERROR] no memory */
            return NULL;
    }

	/* Link the int objects together, from rear to front, then return
	   the address of the last int object in the block. */
	q = p + N_INTOBJECTS;
	while (--q > p) {
		q->v_type = (CoType *)(q-1);
    }
	q->v_type = NULL;

	return p + N_INTOBJECTS - 1;
}

CoValue *CoInt_FromInt(int val)
{
	CoInt *v;

	if (free_list == NULL) {
		if ((free_list = fill_free_list()) == NULL)
			return NULL;
	}

	v = free_list;
	free_list = (CoInt *)v->v_type;
	COVALUE_INIT(v, &CoInt_Type);
	v->i_val = val;
	return (CoValue *)v;
}

int CoInt_AsInt(CoValue *self)
{
    assert(COINT_CHECK(self));

    return ((CoInt *)self)->i_val;
}

static void int_dealloc(CoValue *self)
{
    assert(COINT_CHECK(self));

    self->v_type = (CoType *)free_list;
    free_list = (CoInt *)self;
}

static long int_hash(CoValue *self)
{
    assert(COINT_CHECK(self));

	return ((CoInt *)self)->i_val;
}

static int int_equal(CoValue *va, CoValue *vb)
{
    assert(COINT_CHECK(va));
    assert(COINT_CHECK(vb));

    return ((CoInt *)va)->i_val == ((CoInt *)vb)->i_val;
}

static CoValue *int_str(CoValue *self)
{
    char buf[64 + 2];

    assert(COINT_CHECK(self));

    snprintf(buf, 64, "%d", ((CoInt *) self)->i_val);
    return CoString_FromString(buf);
}

CoType CoInt_Type = {
    "int",
	int_dealloc,                    /* tp_dealloc */
	int_hash,                       /* tp_hash */
    int_equal,                      /* tp_equal */
    int_str,                        /* tp_str */
    0,                              /* tp_iter */
    0,                              /* tp_iternext */
};

